#include "mainwindow.h"
#include "staticfunctions.h"
#include "global.h"
#include "geometryobjects.h"
#include "saveimageseqdialog.h"
#include "enums.h"

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent)
{
  ui.setupUi(this);

  Global::setLutSize(8);
  Global::setStatusBar(ui.statusBar, ui.actionStatusBar);

  ui.statusBar->setEnabled(false);
  ui.statusBar->setSizeGripEnabled(true);
  ui.statusBar->addWidget(Global::progressBar());
  ui.statusBar->hide();

  setAcceptDrops(true);

  m_stackedWidget = new QStackedWidget;

  m_Viewer = new Viewer();
  m_stackedWidget->addWidget(m_Viewer);
  //setCentralWidget(m_Viewer);

  m_ViewerRaycast = new Viewer();
  m_stackedWidget->addWidget(m_ViewerRaycast);

  setCentralWidget(m_stackedWidget);
  m_stackedWidget->setCurrentIndex(0);

  QTextEdit *m_log = new QTextEdit;
  m_Viewer->setLogger(m_log);
  m_ViewerRaycast->setLogger(m_log);

  m_renderProcess = new RenderProcess();
  m_renderProcess->setLogger(m_log);

  m_Viewer->setRenderProcess(m_renderProcess);

  m_tfContainer = new TransferFunctionContainer();
  m_tfManager = new TransferFunctionManager();
  m_tfManager->registerContainer(m_tfContainer);
  m_tfEditor = new TransferFunctionEditorWidget();
  m_tfEditor->setTransferFunction(NULL);
  m_tfManager->setDisabled(true);

  m_keyFrame = new KeyFrame();
  m_Viewer->setKeyFrame(m_keyFrame);

  m_keyFrameEditor = new KeyFrameEditor();
  m_Viewer->setKeyFrameEditor(m_keyFrameEditor);


  m_lightingWidget = new LightingWidget();
  
  Global::setUse1D(false);

  //----------------------------------------------------------
  {
    QDockWidget *dock0 = new QDockWidget("Logger", this);
    dock0->setWidget(m_log);
    dock0->hide();
    dock0->setFeatures(QDockWidget::DockWidgetClosable |
		       QDockWidget::DockWidgetMovable |
		       QDockWidget::DockWidgetFloatable |
		       QDockWidget::DockWidgetVerticalTitleBar);
    ui.menuView->addAction(dock0->toggleViewAction());
    addDockWidget(Qt::BottomDockWidgetArea, dock0);
  }
  //----------------------------------------------------------
  //----------------------------------------------------------
  {
    QDockWidget *dock1 = new QDockWidget("Transfer Function Editor", this);
    dock1->setAllowedAreas(Qt::LeftDockWidgetArea | 
			   Qt::RightDockWidgetArea);
    QSplitter *splitter = new QSplitter(Qt::Vertical, dock1);
    splitter->addWidget(m_tfManager);
    splitter->addWidget(m_tfEditor);
    dock1->setWidget(splitter);
    ui.menuView->addAction(dock1->toggleViewAction());
    addDockWidget(Qt::RightDockWidgetArea, dock1);
  }
  //----------------------------------------------------------
  //----------------------------------------------------------
  {
    QDockWidget *dock2 = new QDockWidget("Shader Widget", this);
    dock2->setAllowedAreas(Qt::LeftDockWidgetArea | 
			   Qt::RightDockWidgetArea);
    dock2->setWidget(m_lightingWidget);
    dock2->hide();
    ui.menuView->addAction(dock2->toggleViewAction());
    addDockWidget(Qt::RightDockWidgetArea, dock2);
  }
  //----------------------------------------------------------
  //----------------------------------------------------------
  {
    m_dockKeyframe = new QDockWidget("KeyFrame Editor", this);
    m_dockKeyframe->setAllowedAreas(Qt::BottomDockWidgetArea | 
				    Qt::TopDockWidgetArea);
    m_dockKeyframe->setWidget(m_keyFrameEditor);
    m_dockKeyframe->hide();
    m_dockKeyframe->setFeatures(QDockWidget::DockWidgetClosable |
				QDockWidget::DockWidgetMovable |
				QDockWidget::DockWidgetFloatable |
				QDockWidget::DockWidgetVerticalTitleBar);
    ui.menuView->addAction(m_dockKeyframe->toggleViewAction());
    addDockWidget(Qt::BottomDockWidgetArea,m_dockKeyframe);
  }
  //----------------------------------------------------------


  StaticFunctions::initQColorDialog();

  #include "connectviewer.h"
  #include "connecttfeditor.h"
  #include "connecttfmanager.h"
  #include "connectlightingwidget.h"
  #include "connectkeyframe.h"
  #include "connectkeyframeeditor.h"


  initializeRecentFiles();

  loadSettings();

  //QTimer::singleShot(1000, this, SLOT(glewInit()));
}

void
MainWindow::glewInit()
{
//  if (!m_ViewerRaycast->isVisible())
//    {
//      m_ViewerRaycast->setVisible(true);
//      m_ViewerRaycast->glewInit();
//      m_ViewerRaycast->setVisible(false);
//    }
//  else
//    m_ViewerRaycast->glewInit();
//
//  if (!m_Viewer->isVisible())
//    {
//      m_Viewer->setVisible(true);
//      m_Viewer->glewInit();
//      m_Viewer->setVisible(false);
//    }
//  else
//    m_Viewer->glewInit();
}

void
MainWindow::loadSettings()
{
  QString homePath = QDir::homePath();
  QFileInfo settingsFile(homePath, ".mahadrishti.xml");

  if (! settingsFile.exists())
    return;

  QString flnm = settingsFile.absoluteFilePath();  


  QDomDocument document;
  QFile f(flnm.toAscii().data());
  if (f.open(QIODevice::ReadOnly))
    {
      document.setContent(&f);
      f.close();
    }

  QDomElement main = document.documentElement();
  QDomNodeList dlist = main.childNodes();
  for(int i=0; i<dlist.count(); i++)
    {
      if (dlist.at(i).nodeName() == "texturememory")
	{
	  QString str = dlist.at(i).toElement().text();
	  Global::setTextureMemorySize(str.toInt());
	  Global::calculate3dTextureSize();
	}
      else if (dlist.at(i).nodeName() == "texturesizelimit")
	{
	  QString str = dlist.at(i).toElement().text();
	  Global::setTextureSizeLimit(str.toInt());
	}
      else if (dlist.at(i).nodeName() == "tempdirectory")
	{
	  QString str = dlist.at(i).toElement().text();
	  Global::setTempDir(str);
	}
      else if (dlist.at(i).nodeName() == "previousdirectory")
	{
	  QString str = dlist.at(i).toElement().text();
	  Global::setPreviousDirectory(str);
	}
      else if (dlist.at(i).nodeName() == "recentfile")
	{
	  QString str = dlist.at(i).toElement().text();
	  Global::addRecentFile(str);
	}
      else if (dlist.at(i).nodeName() == "replacetf")
	{
	  QString str = dlist.at(i).toElement().text();
	  if (str == "true")
	    m_tfManager->updateReplace(true);
	  else
	    m_tfManager->updateReplace(false);
	}
      else if (dlist.at(i).nodeName() == "floatprecision")
	{
	  QString str = dlist.at(i).toElement().text();
	  Global::setFloatPrecision(str.toInt());
	}
    }
  //m_preferencesWidget->updateTextureMemory();
  //m_preferencesWidget->load(flnm.toAscii().data());
  updateRecentFileAction();
}

void
MainWindow::saveSettings()
{
  QString str;
  QDomDocument doc("mahaDrishti_v0.1");

  QDomElement topElement = doc.createElement("DrishtiGlobalSettings");
  doc.appendChild(topElement);

  {
    QDomElement de0 = doc.createElement("texturememory");
    QDomText tn0;
    tn0 = doc.createTextNode(QString("%1").arg(Global::textureMemorySize()));
    de0.appendChild(tn0);
    topElement.appendChild(de0);
  }

  {
    QDomElement de0 = doc.createElement("texturesizelimit");
    QDomText tn0;
    tn0 = doc.createTextNode(QString("%1").arg(Global::textureSizeLimit()));
    de0.appendChild(tn0);
    topElement.appendChild(de0);
  }

  {
    QDomElement de0 = doc.createElement("tempdirectory");
    QDomText tn0;
    tn0 = doc.createTextNode(Global::tempDir());
    de0.appendChild(tn0);
    topElement.appendChild(de0);
  }

  {
    QDomElement de0 = doc.createElement("previousdirectory");
    QDomText tn0;
    tn0 = doc.createTextNode(Global::previousDirectory());
    de0.appendChild(tn0);
    topElement.appendChild(de0);
  }

  {
    QStringList rf = Global::recentFiles();
    for (int i=0; i<rf.count(); i++)
      {
	QDomElement de0 = doc.createElement("recentfile");
	QDomText tn0;
	tn0 = doc.createTextNode(rf[i]);
	de0.appendChild(tn0);
	topElement.appendChild(de0);
      }
  }

  {
    QDomElement de0 = doc.createElement("replacetf");
    QDomText tn0;
    tn0 = doc.createTextNode(QString("%1").arg(Global::replaceTF()));
    de0.appendChild(tn0);
    topElement.appendChild(de0);
  }

  {
    QDomElement de0 = doc.createElement("floatprecision");
    QDomText tn0;
    tn0 = doc.createTextNode(QString("%1").arg(Global::floatPrecision()));
    de0.appendChild(tn0);
    topElement.appendChild(de0);
  }

  QString homePath = QDir::homePath();
  QFileInfo settingsFile(homePath, ".mahadrishti.xml");
  QString flnm = settingsFile.absoluteFilePath();  

  QFile f(flnm.toAscii().data());
  if (f.open(QIODevice::WriteOnly))
    {
      QTextStream out(&f);
      doc.save(out, 2);
      f.close();
    }
  else
    QMessageBox::information(0, "Cannot save ", flnm.toAscii().data());


  //m_preferencesWidget->save(flnm.toAscii().data());
}

void
MainWindow::on_actionExit_triggered()
{
  close();
}

void
MainWindow::on_actionRaycast_triggered()
{
  int ci = m_stackedWidget->currentIndex();
  m_stackedWidget->setCurrentIndex((ci+1)%2);

//  {
//    int ci = m_stackedWidget->currentIndex();
//    if (ci == 0)
//      m_ViewerRaycast->makeCurrent();
//    else
//      m_Viewer->makeCurrent();
//  }
}

void
MainWindow::closeEvent(QCloseEvent*)
{
  // stop playing keyframes
  m_keyFrameEditor->setPlayFrames(false);

  saveSettings();

  QList<QString> vfile = m_Viewer->volumeFilename();
  if (vfile.count() == 0)
    return;


  int ok = QMessageBox::question(0, "Exit Drishti",
	  QString("Would you like to save project before quiting ?"),
				 QMessageBox::Yes | QMessageBox::No);

  if (ok == QMessageBox::Yes)
    on_actionSave_Project_triggered();
}

void
MainWindow::on_actionImage_Size_triggered()
{
  QSize scrSize = m_Viewer->size();

  QStringList items;
  items << QString("%1 %2 (Current)").arg(scrSize.width()).arg(scrSize.height());
  items << "256 256";
  items << "512 512";
  items << "320 240";
  items << "480 270";
  items << "640 480";
  items << "720 480 (NTSC)";
  items << "720 576 (PAL)";
  items << "800 600";
  items << "960 540";
  items << "1024 768 (XGA)";
  items << "1280 1024";
  items << "1400 1050";
  items << "1600 1200";
  items << "1920 1080 (HD)";

  bool ok;
  QString str;
  str = QInputDialog::getItem(this,
			      "Set Image Size",
			      "Image Size",
			      items,
			      0,
			      true, // text is editable
			      &ok);
  
  if (ok)
    {
      QStringList strlist = str.split(" ", QString::SkipEmptyParts);
      int x=0, y=0;
      if (strlist.count() > 1)
	{
	  x = strlist[0].toInt(&ok);
	  y = strlist[1].toInt(&ok);
	}

      if (x > 0 && y > 0)
	{
	  if (statusBar()->isVisible())
	    resize(x,
		   y + (menuBar()->size().height() +
			statusBar()->size().height()));
	  else
	    resize(x,
		   y + menuBar()->size().height());
	}
      else
	QMessageBox::information(0, "Image Size",
				 "Image Size improperly set : "+str);

    }

}

void
MainWindow::on_actionStatusBar_triggered()
{
  if (ui.actionStatusBar->isChecked())
    ui.statusBar->show();
  else
    ui.statusBar->hide();
}

void
MainWindow::on_actionLoad_Volume_triggered()
{
  QString flnm;
  flnm = QFileDialog::getOpenFileName(0,
				      "Load volume",
				      QCoreApplication::applicationDirPath(),
				      "Files (*.bvf | *.h5)");
  
  if (flnm.isEmpty())
    return;

  if (StaticFunctions::checkExtension(flnm, ".bvf"))
    {
      flnm.chop(3);
      flnm += "h5";
      QFileInfo finfo(flnm);
      if (!finfo.exists() || !finfo.isFile())
	{
	  QMessageBox::information(0, "", QString("File %1 not found").arg(flnm));
	  return;
	}
    }

  Global::addRecentFile(flnm);
  updateRecentFileAction();

  loadVolume(flnm);
}

void
MainWindow::loadVolume(QString flnm)
{
  QList<QString> vflnm;
  vflnm.append(flnm);
  m_Viewer->loadVolume(vflnm);

  m_tfEditor->setTransferFunction(NULL);
  m_tfManager->clearManager();
  m_tfManager->setDisabled(false);
  m_tfManager->loadDefaultTF();
  changeHistogram(0);
}
void
MainWindow::loadVolume(QList<QString> flnm)
{
  m_Viewer->loadVolume(flnm);

  m_tfEditor->setTransferFunction(NULL);
  m_tfManager->clearManager();
  m_tfManager->setDisabled(false);
  m_tfManager->loadDefaultTF();
  changeHistogram(0);
}

void
MainWindow::on_actionSwitch_To1D_triggered()
{
  Global::setUse1D(!Global::use1D());
  ui.actionSwitch_To1D->setChecked(Global::use1D());
  m_tfContainer->switch1D();

  if (Global::use1D())
    QMessageBox::information(0, "", "Switching to 1D Transfer Functions");
  else
    QMessageBox::information(0, "", "Switching to 2D Transfer Functions");
}

void
MainWindow::checkStateChanged(int i, int j, bool flag)
{
  updateComposite();
}

void
MainWindow::updateComposite()
{
  //QImage colorMap = m_tfContainer->composite(0);
  //m_Viewer->loadLookupTable(colorMap);

  QList<QImage> imgList;
  for(int i=0; i<Global::lutSize(); i++)
    imgList.append(m_tfContainer->composite(i));

  m_Viewer->loadLookupTable(imgList);
}

void
MainWindow::applyTFUndo(bool flag)
{
  m_tfManager->applyUndo(flag);
}

void
MainWindow::transferFunctionUpdated()
{
  m_tfManager->transferFunctionUpdated();
}

void
MainWindow::changeTransferFunctionDisplay(int tfnum, QList<bool> on)
{
  if (tfnum >= 0)
    {
      SplineTransferFunction *sptr = m_tfContainer->transferFunctionPtr(tfnum);
      m_tfEditor->setTransferFunction(sptr);
    }
  else
    m_tfEditor->setTransferFunction(NULL);    

  updateComposite();
}


void
MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
  if (event && event->mimeData())
    {
      const QMimeData *data = event->mimeData();
      if (data->hasUrls())
	{
	  QUrl url = data->urls()[0];
	  QFileInfo info(url.toLocalFile());
	  if (info.exists() && info.isFile())
	    {
	      QList<QUrl> urls;
	      urls << url;
	      if (StaticFunctions::checkURLs(urls, ".xml"))
		{
		  event->acceptProposedAction();
		  return;
		}

	      QString flnm;
	      flnm = (data->urls())[0].toLocalFile();
	      bool ok = false;
	      if (StaticFunctions::checkExtension(flnm, ".bvf"))
		{
		  flnm.chop(3);
		  flnm += "h5";
		  QFileInfo finfo(flnm);
		  if (finfo.exists() && finfo.isFile())
		    ok = true;
		  else
		    QMessageBox::information(0, "", flnm);
		}
	      if (StaticFunctions::checkExtension(flnm, ".h5"))
		ok = true;

	      if (ok)
		event->acceptProposedAction();
	    }
	}
    }
}

void
MainWindow::dropEvent(QDropEvent *event)
{
  if (event && event->mimeData())
    {
      const QMimeData *data = event->mimeData();
      if (data->hasUrls())
	{
	  QUrl url = data->urls()[0];
	  QFileInfo info(url.toLocalFile());
	  if (info.exists() && info.isFile())
	    {
	      if (StaticFunctions::checkExtension(url.toLocalFile(), ".xml"))
		{
		  Global::addRecentFile(url.toLocalFile());
		  updateRecentFileAction();
		  loadProject(url.toLocalFile().toAscii().data());
		  return;
		}

	      QStringList flist;
	      QList<QUrl> urls = data->urls();
	      for(int i=0; i<urls.count(); i++)
		{
		  QString flnm;
		  flnm = urls[i].toLocalFile();

		  bool ok = false;
		  if (StaticFunctions::checkExtension(flnm, ".bvf"))
		    {
		      flnm.chop(3);
		      flnm += "h5";
		      QFileInfo finfo(flnm);
		      if (finfo.exists() && finfo.isFile())
			ok = true;
		    }
		  if (StaticFunctions::checkExtension(flnm, ".h5"))
		    ok = true;
						
		  if (ok)
		    flist.append(flnm);
		}
		  
	      loadVolume(flist);

	      Global::addRecentFile(flist[0]);
	      updateRecentFileAction();
	    }
	}
    }
}

void
MainWindow::changeHistogram(int volnum)
{
  emit histogramUpdated(m_Viewer->histogramImage1D(),
			m_Viewer->histogramImage2D());
}

void
MainWindow::on_actionSave_ImageSequence_triggered()
{
  QSize imgSize = StaticFunctions::getImageSize(m_Viewer->size().width(),
						m_Viewer->size().height());

  //m_Viewer->setImageSize(imgSize.width(), imgSize.height());
  if (statusBar()->isVisible())
    resize(imgSize.width(),
	   imgSize.height() + (menuBar()->size().height() +
			       statusBar()->size().height()));
  else
    resize(imgSize.width(),
	   imgSize.height() + menuBar()->size().height());

  SaveImageSeqDialog saveImg(0,
			     Global::previousDirectory(),
			     m_keyFrameEditor->startFrame(),
			     m_keyFrameEditor->endFrame(),
			     1);

  saveImg.move(QCursor::pos());

  if (saveImg.exec() == QDialog::Accepted)
    {
      QString flnm = saveImg.fileName();
      int imgMode = saveImg.imageMode();

      if (imgMode == Enums::CubicImageMode)
	{
	  if (imgSize.width() != imgSize.height())
	    {
	      QMessageBox::critical(0, "Error",
				    QString("Current image size is %1x%2.\nSquare image size required for cubic images.").\
				    arg(imgSize.width()).\
				    arg(imgSize.height()));
	      return;
	    }
	}

      QFileInfo f(flnm);
      Global::setPreviousDirectory(f.absolutePath());

      m_Viewer->setImageMode(imgMode);
      m_Viewer->setImageFileName(flnm);
      m_Viewer->setSaveSnapshots(true);
      
      m_Viewer->dummydraw();

      connect(this, SIGNAL(playKeyFrames(int,int,int)),
	      m_keyFrameEditor, SLOT(playKeyFrames(int,int,int)));
      emit playKeyFrames(saveImg.startFrame(),
			 saveImg.endFrame(),
			 saveImg.stepFrame());
      qApp->processEvents();
      disconnect(this, SIGNAL(playKeyFrames(int,int,int)),
		 m_keyFrameEditor, SLOT(playKeyFrames(int,int,int)));
    }
}

void
MainWindow::loadProject(const char* flnm)
{
  if (! GlewInit::initialised())
    {
      QMessageBox::information(0, "Drishti", "Not yet ready to start work!");
      return;
    }

  Global::disableViewerUpdate();

  Global::setCurrentProjectFile(QString(flnm));

  QFileInfo f(flnm);
  Global::setPreviousDirectory(f.absolutePath());

  QList<QString> h5file = loadVolumeFromProject(flnm);
  if (h5file.count() == 0)
    return;

  m_Viewer->loadVolume(h5file);

  Vec bs4d = m_Viewer->boxSize4D();
  if (bs4d.x > 0.001) // we have a timeseries
    m_Viewer->setBoxSize(1); // set initial box size

  m_keyFrame->clear();
  m_keyFrameEditor->clear();

  m_tfEditor->setTransferFunction(NULL);
  m_tfManager->clearManager();
  m_tfManager->setDisabled(false);
  m_tfManager->load(flnm);
  changeHistogram(0);
  
  loadViewsAndKeyFrames(flnm);

  updateComposite();

  Global::enableViewerUpdate();

  m_keyFrame->playSavedKeyFrame();

  m_Viewer->toggleBounds();
}

void
MainWindow::saveProject(const char* flnm)
{
  Vec pos;
  Quaternion rot;
  pos = m_Viewer->camera()->position();
  rot = m_Viewer->camera()->orientation();

  Vec bmin, bmax;
  m_Viewer->bounds(bmin, bmax);

  QImage image = m_Viewer->grabFrameBuffer();
  image = image.scaled(100, 100);

  ClipInformation clipInfo;
  clipInfo = GeometryObjects::clipplanes()->clipInfo();

  Vec bs4d = m_Viewer->boxSize4D();
  int ts = m_Viewer->timeStep();
  if (bs4d.x > 0.001)
    {
      // we are handling 4d volume so
      // modify the camera position to make it
      // with respect to the centroid of the bounding box
      Vec cen = (bmax+bmin)/2;
      pos -= cen;

      if (ts >= 0)
	{
	  Vec corner = Vec(bs4d.z, bs4d.y, bs4d.x*ts);
	  bmin -= corner;
	  bmax -= corner;
	}

      //-----------------------------------------------------
      // modify clipInfo before saving
      int nclip = clipInfo.size();
      if (nclip > 0) 
	{
	  // we are handling 4d volume so
	  // modify the clip position to make it
	  // with respect to the centroid of the bounding box
	  float b = bs4d.x * ts;
	  QList<Vec> cpos;
	  cpos = clipInfo.pos;
	  for(int ci=0; ci<nclip; ci++)
	    cpos[ci].z -= b;
	  
	  clipInfo.pos = cpos;
	}
      //-----------------------------------------------------

    }


  m_keyFrame->saveProject(pos, rot,
			  bs4d, ts,
			  image,
			  bmin, bmax,
			  m_Viewer->getLUT(),
			  clipInfo,
			  m_Viewer->lightInfo());


  saveVolumeIntoProject(flnm);
  m_tfManager->save(flnm);
  saveViewsAndKeyFrames(flnm);

  QFileInfo f(flnm);
  Global::setPreviousDirectory(f.absolutePath());
  Global::setCurrentProjectFile(QString(flnm));

  QMessageBox::information(0, "Saved project to", flnm); 
}

void
MainWindow::on_actionLoad_Project_triggered()
{
  QString flnm;
  flnm = QFileDialog::getOpenFileName(0,
				      "Load Project",
				      Global::previousDirectory(),
				      "xml Files (*.xml)",
				      0,
				      QFileDialog::DontUseNativeDialog);


  if (flnm.isEmpty())
    return;

  Global::addRecentFile(flnm);
  updateRecentFileAction();
  loadProject(flnm.toAscii().data());
}

void
MainWindow::on_actionSave_Project_triggered()
{
  QString flnm;
  flnm = Global::currentProjectFile();

  if (flnm.isEmpty())
    flnm = QFileDialog::getSaveFileName(0,
					"Save Project",
					Global::previousDirectory(),
					"xml Files (*.xml)",
					0,
					QFileDialog::DontUseNativeDialog);


  if (flnm.isEmpty())
    return;

  if (!StaticFunctions::checkExtension(flnm, ".xml"))
    flnm += ".xml";
  
  saveProject(flnm.toAscii().data());
}
void
MainWindow::on_actionSave_ProjectAs_triggered()
{
  QString flnm;
  flnm = QFileDialog::getSaveFileName(0,
				      "Save Project As",
				      Global::previousDirectory(),
				      "xml Files (*.xml)",
				      0,
				      QFileDialog::DontUseNativeDialog);


  if (flnm.isEmpty())
    return;

  if (!StaticFunctions::checkExtension(flnm, ".xml"))
    flnm += ".xml";

  saveProject(flnm.toAscii().data());
}

void
MainWindow::on_actionSpline_PositionInterpolation_triggered()
{
  bool cpi = Global::interpolationType(Global::CameraPositionInterpolation);
  Global::setInterpolationType(Global::CameraPositionInterpolation, !cpi);
  ui.actionSpline_PositionInterpolation->setChecked(Global::interpolationType(Global::CameraPositionInterpolation));
}

QList<QString>
MainWindow::loadVolumeFromProject(const char *flnm)
{
  QList<QString> h5file;

  int volType = Global::DummyVolume;

  QDomDocument document;
  QFile f(flnm);
  if (f.open(QIODevice::ReadOnly))
    {
      document.setContent(&f);
      f.close();
    }

  QDomElement main = document.documentElement();
  QDomNodeList dlist = main.childNodes();
  for(int i=0; i<dlist.count(); i++)
    {
      if (dlist.at(i).nodeName() == "texsizereducefraction")
	{
	  QString str = dlist.at(i).toElement().text();
	  float rlod = str.toFloat();
	  Global::setTexSizeReduceFraction(rlod);
	}
      else if (dlist.at(i).nodeName() == "floatprecision")
	{
	  QString str = dlist.at(i).toElement().text();
	  Global::setFloatPrecision(str.toInt());
	}
      else if (dlist.at(i).nodeName() == "drawbox")
	{
	  QString str = dlist.at(i).toElement().text();
	  if (str == "true")
	    Global::setDrawBox(true);
	  else
	    Global::setDrawBox(false);
	}
      else if (dlist.at(i).nodeName() == "drawaxis")
	{
	  QString str = dlist.at(i).toElement().text();
	  if (str == "true")
	    Global::setDrawAxis(true);
	  else
	    Global::setDrawAxis(false);
	}
      else if (dlist.at(i).nodeName() == "using1d")
	{
	  QString str = dlist.at(i).toElement().text();
	  if (str == "true")
	    Global::setUse1D(true);
	  else
	    Global::setUse1D(false);
	}
      else if (dlist.at(i).nodeName() == "volumefiles")
	{
	  // for loading volume file names with relative path
	  QFileInfo fileInfo(flnm);
	  QDir direc = fileInfo.absoluteDir();

	  QDomNodeList vlist = dlist.at(i).childNodes();
	  for(int vi=0; vi<vlist.count(); vi++)
	    {
	      QString str = vlist.at(vi).toElement().text();
	      QString vfile = direc.absoluteFilePath(str);
	      h5file.append(vfile);
	    }
	}
      else if (dlist.at(i).nodeName() == "volsize4d")
	{
	  QString str = dlist.at(i).toElement().text();
	  QStringList words = str.split(" ", QString::SkipEmptyParts);
	  float x, y, z;
	  x = words[0].toFloat();
	  y = words[1].toFloat();
	  z = words[2].toFloat();
	  m_Viewer->set4DboxSize(Vec(x,y,z));
	}

    }

  for(int nf=0; nf<h5file.count(); nf++)
    {
      if (StaticFunctions::checkExtension(h5file[nf], ".bvf"))
	{
	  h5file[nf].chop(3);
	  h5file[nf] += "h5";
	  QFileInfo finfo(h5file[nf]);
	  if (!finfo.exists() || !finfo.isFile())
	    {
	      QMessageBox::information(0, "", QString("File %1 not found").arg(h5file[nf]));
	      return QList<QString>();
	    }
	}
    }

  return h5file;
}

void
MainWindow::saveVolumeIntoProject(const char *flnm)
{
  QString str;

  QDomDocument doc("mahaDrishti_v0.1");

  QDomElement topElement = doc.createElement("Drishti");
  doc.appendChild(topElement);

  {
    QDomElement de0 = doc.createElement("texsizereducefraction");
    QDomText tn0;
    tn0 = doc.createTextNode(QString("%1").arg(Global::texSizeReduceFraction()));
    de0.appendChild(tn0);
    topElement.appendChild(de0);
  }

  {
    QDomElement de0 = doc.createElement("floatprecision");
    QDomText tn0;
    tn0 = doc.createTextNode(QString("%1").arg(Global::floatPrecision()));
    de0.appendChild(tn0);
    topElement.appendChild(de0);
  }

  {
    QDomElement de0 = doc.createElement("drawbox");
    QDomText tn0;
    if (Global::drawBox())
      tn0 = doc.createTextNode("true");
    else
      tn0 = doc.createTextNode("false");
    de0.appendChild(tn0);
    topElement.appendChild(de0);
  }

  {
    QDomElement de0 = doc.createElement("drawaxis");
    QDomText tn0;
    if (Global::drawAxis())
      tn0 = doc.createTextNode("true");
    else
      tn0 = doc.createTextNode("false");
    de0.appendChild(tn0);
    topElement.appendChild(de0);
  }

  {
    QDomElement de0 = doc.createElement("using1d");
    QDomText tn0;
    if (Global::use1D())
      tn0 = doc.createTextNode("true");
    else
      tn0 = doc.createTextNode("false");
    de0.appendChild(tn0);
    topElement.appendChild(de0);
  }

  {
    // for saving volume file names with relative path
    QFileInfo fileInfo(flnm);
    QDir direc = fileInfo.absoluteDir();

    QDomElement dev = doc.createElement("volumefiles");
    QList<QString> files = m_Viewer->volumeFilename();
    for(int i=0; i<files.count(); i++)
      {
	QDomElement de0 = doc.createElement("name");
	// saving volume filenames relative to the project file path
	QString relFile = direc.relativeFilePath(files[i]);
	QDomText tn0 = doc.createTextNode(relFile);
	de0.appendChild(tn0);
	dev.appendChild(de0);
      }
    topElement.appendChild(dev);
  }

  {
    Vec bs4d = m_Viewer->boxSize4D();
    QDomElement de0 = doc.createElement("volsize4d");
    QDomText tn0;
    tn0 = doc.createTextNode(QString("%1 %2 %3").\
			     arg(bs4d.x).arg(bs4d.y).arg(bs4d.z));
    de0.appendChild(tn0);
    topElement.appendChild(de0);
  }

  QFile f(flnm);
  if (f.open(QIODevice::WriteOnly))
    {
      QTextStream out(&f);
      doc.save(out, 2);
      f.close();
    }
}

void
MainWindow::loadViewsAndKeyFrames(const char* flnm)
{
  QString sflnm(flnm);
  sflnm.replace(QString(".xml"), QString(".keyframes"));

  QFileInfo fileInfo(sflnm);
  if (! fileInfo.exists())
    return;

  fstream fin(sflnm.toAscii().data(), ios::binary|ios::in);

  char keyword[100];
  fin.getline(keyword, 100, 0);
  if (strcmp(keyword, "mahaDrishti Keyframes") != 0)
    {
      QMessageBox::information(0, "Load Keyframes",
			       QString("Invalid .keyframes file : ")+sflnm);
      return;
    }

  while (!fin.eof())
    {
      fin.getline(keyword, 100, 0);
      if (strcmp(keyword, "keyframes") == 0)
	m_keyFrame->load(fin);
    }
  fin.close();
}

void
MainWindow::saveViewsAndKeyFrames(const char* flnm)
{
  QString sflnm(flnm);
  sflnm.replace(QString(".xml"), QString(".keyframes"));

  fstream fout(sflnm.toAscii().data(), ios::binary|ios::out);

  char keyword[100];

  memset(keyword, 0, 100);
  sprintf(keyword, "mahaDrishti Keyframes");
  fout.write((char*)keyword, strlen(keyword)+1);  

  m_keyFrame->save(fout);

  fout.close();
}

void
MainWindow::initializeRecentFiles()
{
  for(int i=0; i<m_recentFileActions.count(); i++)
    delete m_recentFileActions[i];
  m_recentFileActions.clear();

  for (int i=0; i<Global::maxRecentFiles(); i++)
    {
      m_recentFileActions.append(new QAction(this));
      m_recentFileActions[i]->setVisible(false);
      connect(m_recentFileActions[i], SIGNAL(triggered()),
	      this, SLOT(openRecentFile()));
      ui.menuFile->insertAction(ui.actionExit,
				m_recentFileActions[i]);
    }

  ui.menuFile->insertSeparator(ui.actionExit);
}

void
MainWindow::openRecentFile()
{
  QAction *action = qobject_cast<QAction *>(sender());
  if (action)
    {
      QString filename = action->data().toString();
      QFileInfo fileInfo(filename);
      if (! fileInfo.exists())
	{
	  QMessageBox::information(0, "Error",
				   QString("Cannot locate ") +
				   filename +
				   QString(" for loading"));
	  return;
	}

      if (StaticFunctions::checkExtension(filename, ".bvf"))
	{
	  filename.chop(3);
	  filename += "h5";
	  QFileInfo finfo(filename);
	  if (!finfo.exists() || !finfo.isFile())
	    {
	      QMessageBox::information(0, "",
				       QString("File %1 not found").arg(filename));
	      return;
	    }
	  loadVolume(filename);
	}
      else if (StaticFunctions::checkExtension(filename, ".h5"))
	{
	  loadVolume(filename);
	}
      else if (StaticFunctions::checkExtension(filename, ".xml"))
	{
	  Global::addRecentFile(filename);
	  updateRecentFileAction();
	  loadProject(filename.toAscii().data());
	}
    }
}

void
MainWindow::updateRecentFileAction()
{
  QStringList rf = Global::recentFiles();
  for(int i=0; i<rf.count(); i++)
    {
      QString flnm = QFileInfo(rf[i]).fileName();
      QString text = QString("&%1. %2").arg(i+1).arg(flnm);
      m_recentFileActions[i]->setText(text);
      m_recentFileActions[i]->setData(rf[i]);
      m_recentFileActions[i]->setVisible(true);
    }
  for(int i=rf.count(); i<Global::maxRecentFiles(); i++)
    m_recentFileActions[i]->setVisible(false);

}

void
MainWindow::updateTransferFunctionManager(QList<SplineInformation> splineInfo)
{
  m_tfManager->load(splineInfo);
}
void MainWindow::updateMorph(bool flag) { m_tfManager->updateMorph(flag); }

void
MainWindow::setKeyFrame(Vec pos, Quaternion rot,
			int fno,
			Vec bs4d, int ts,
			QImage image,
			Vec bmin, Vec bmax,
			float *lut)
{
  QList<SplineInformation> splineInfo;
  for(int i=0; i<m_tfContainer->count(); i++)
    {
      SplineTransferFunction *sptr = m_tfContainer->transferFunctionPtr(i);
      splineInfo.append(sptr->getSpline());
    }

  m_keyFrame->setKeyFrame(pos, rot,
			  fno,
			  bs4d, ts,
			  image,
			  bmin, bmax,
			  lut,
			  splineInfo,
			  m_Viewer->lightInfo());
}

